今天大概會聊到的範圍
- Theme
透過 Android Studio 內建的精靈建立一個新的 Compose 專案或是建立新的 "Empty Compose Activity" 時,會發現這樣的 code :
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ProjectNameTheme {  // <--- 今天主角
                // A surface container using the 'background' color from the theme
                Surface(color = MaterialTheme.colors.background) {
                    Greeting("Android")
                }
            }
        }
    }
}
可以發現預設的 Code 會在內容的 Composable 之外,再包一個 Theme。仔細研究一下這個 Theme。這個 Theme 通常是開啟新的 Compose 專案時自動建立的。可以觀察到這個 Theme 其實是對 MaterialTheme 的包裝。
@Composable
fun ProjectNameTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),    
    content: @Composable () -> Unit
) {
    val colors = if (darkTheme) {
        DarkColorPalette
    } else {
        LightColorPalette
    }
    
    MaterialTheme(
        colors = colors,
        typography = Typography,
        shapes = Shapes,
        content = content
    )
}
在 MaterialTheme 中,要提供 color 、typography、shapes。
    val colors = if (darkTheme) {
        DarkColorPalette
    } else {
        LightColorPalette
    }
在 Android Studio 自動建立的 Theme 中,會判斷是否是 dark mode,在不同的情況下使用不同的 "ColorPalette"
Color Palette 是 Material Design 中重要的概念。透過一組事先配好的顏色讓整個 App 的顏色有一致性。要提供 MaterialTheme color,我們要提供的 Colors 物件時就需要提供這個 Palette 中所需要的各個顏色:
class Colors(
    primary: Color,
    primaryVariant: Color,
    secondary: Color,
    secondaryVariant: Color,
    background: Color,
    surface: Color,
    error: Color,
    onPrimary: Color,
    onSecondary: Color,
    onBackground: Color,
    onSurface: Color,
    onError: Color,
    isLight: Boolean    // 是否是 dark mode 
)
除了顏色之外,typography 可以定義 h1 ~ body 等不同字級。可以參考 Material Design 的 Type System 、另外還有 Shape System 可以設定在不同的情況下物件的形狀。
Theme 已經配置好了,我們也將 content 包在 Theme 裡面了,那要怎麼取得我們 Theme 的配置呢?
@Composable
fun UIComposable() {
    MaterialTheme() {
        Card(modifier = Modifier.background(MaterialTheme.colors.background)) {
            // ...
        }
    }
}
我們只需要透過 MaterialTheme.(colors | typography | shapes) 就可以取得對應的參數了!
在 Compose 中,使用 Theme 真的非常的簡單,設定的地方和使用的地方都非常直覺。很好奇 Compose framework 實際上怎麼做到這件事的? 也許可以當成後續的主題吧!
Reference: